package com.bsg.upm.service;

import java.text.MessageFormat;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bsg.upm.check.CheckResult;
import com.bsg.upm.check.SanCheck;
import com.bsg.upm.constant.OperateDictConstants;
import com.bsg.upm.constant.OperateDictTypeConstants;
import com.bsg.upm.constant.SysConstants;
import com.bsg.upm.dto.SanDto;
import com.bsg.upm.dto.SanVendorDto;
import com.bsg.upm.entity.SanEntity;
import com.bsg.upm.entity.SanVendorEntity;
import com.bsg.upm.entity.SiteEntity;
import com.bsg.upm.entity.UserEntity;
import com.bsg.upm.exception.APIException;
import com.bsg.upm.http.RespJson;
import com.bsg.upm.http.RespJsonFactory;
import com.bsg.upm.util.DateUtils;
import com.bsg.upm.util.PrimaryKeyUtils;

/**
 * SAN管理业务处理类
 * 
 * @author HCK
 *
 */
@Service
public class SanService extends BaseService {

	@Resource
	private SanCheck sanCheck;

	/**
	 * SAN查询
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	public RespJson list(Map<String, Object> paramMap) throws APIException {
		try {
			// 结果集
			JSONArray results = new JSONArray();

			// 获取指定条件的区域
			List<SanEntity> sans = sanDao.list(paramMap);
			if (sans.size() > 0) {
				String siteId = (String) paramMap.get("siteId");

				// 从MGM获取SAN信息
				JSONArray mgmSanInfos = listSanInfoFromMGM(siteId);

				for (SanEntity san : sans) {
					// 从MGM SAN信息列表中获取指定的SAN信息
					JSONObject mgmSanInfo = findSanInfoFromMGM(mgmSanInfos, san.getRelateId());
					// 构建SAN展示对象
					SanDto sanDto = buildShowDto(san, false, mgmSanInfo);
					results.add(sanDto);
				}
			}

			return RespJsonFactory.buildOK(results);
		} catch (Exception e) {
			logger.error("SAN查询异常", e);
			throw new APIException("SAN查询异常:" + e.getMessage());
		}
	}

	/**
	 * SAN新增
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	@Transactional(rollbackFor = APIException.class)
	public RespJson save(Map<String, Object> paramMap) throws APIException {
		// 操作动作
		String operateAcion = OperateDictConstants.ACTION_ADD;
		String operateAcionText = dictTypeCache.getTextFromCache(OperateDictTypeConstants.OPERATE_ACTION, operateAcion);
		try {
			// SAN新增检查
			CheckResult chkRS = sanCheck.checkSave(paramMap);
			if (chkRS.isError()) {
				return RespJsonFactory.build(chkRS.getStatus(), chkRS.getErrorMsg());
			}

			// 构建SAN对象
			SanEntity san = buildSan(paramMap);
			sanDao.save(san);

			// 向MGM注册SAN信息
			JSONObject respJson = saveSanToMGM(san.getSite().getId(), paramMap);

			// 保存MGM SAN编码
			san.setRelateId(respJson.getString("id"));
			sanDao.updateRelateId(san);

			// 保存操作日志
			saveOperateLog(OperateDictConstants.MODEL_SAN, operateAcion, san.getId(), san.getName(),
					san.getCreateDateTime());

			return RespJsonFactory.buildCreated();
		} catch (Exception e) {
			logger.error("SAN" + operateAcionText + "异常", e);
			throw new APIException("SAN" + operateAcionText + "异常");
		}
	}

	/**
	 * SAN删除
	 * 
	 * @param id
	 *            SAN编码
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	@Transactional(rollbackFor = APIException.class)
	public RespJson remove(String id) throws APIException {
		// 操作动作
		String operateAcion = OperateDictConstants.ACTION_REMOVE;
		String operateAcionText = dictTypeCache.getTextFromCache(OperateDictTypeConstants.OPERATE_ACTION, operateAcion);
		try {
			// 获取指定的SAN
			SanEntity san = sanDao.get(id);

			// SAN删除检查
			CheckResult chkRS = sanCheck.checkRemove(san);
			if (chkRS.isError()) {
				return RespJsonFactory.build(chkRS.getStatus(), chkRS.getErrorMsg());
			}

			sanDao.remove(id);

			// 站点
			String siteId = san.getSite().getId();
			// 从MGM删除SAN信息
			removeSanFromMGM(siteId, san.getRelateId());

			// 保存操作日志
			saveOperateLog(OperateDictConstants.MODEL_SAN, operateAcion, san.getId(), san.getName());

			return RespJsonFactory.buildNoContent();
		} catch (Exception e) {
			logger.error("SAN" + operateAcionText + "异常", e);
			throw new APIException("SAN" + operateAcionText + "异常" + e.getMessage());
		}
	}

	/**
	 * 从MGM获取SAN信息
	 * 
	 * @param siteId
	 *            站点编码
	 * @return JSONArray MGM SAN集合
	 * @throws APIException
	 *             API异常处理类
	 */
	private JSONArray listSanInfoFromMGM(String siteId) throws APIException {
		String urlPattern = "/{0}/storage/san";
		String url = MessageFormat.format(urlPattern, SysConstants.MGM_VERSION);
		RespJson httpRespJson = sendHttpGet(siteId, SysConstants.INTERFACE_TYPE_MGM, url);
		if (httpRespJson.getStatus() == HttpStatus.SC_OK) {
			return ((JSONArray) httpRespJson.getData());
		} else {
			throw new APIException(httpRespJson.getMsg());
		}
	}

	/**
	 * 从MGM SAN信息列表中获取指定的SAN信息
	 * 
	 * @param mgmSanInfos
	 *            MGM SAN信息集合
	 * @param mgmSanId
	 *            MGM SAN编码
	 * @return MGM SAN信息
	 */
	private JSONObject findSanInfoFromMGM(JSONArray mgmSanInfos, String mgmSanId) {
		if (mgmSanInfos == null) {
			return null;
		}
		for (int i = 0; i < mgmSanInfos.size(); i++) {
			JSONObject mgmSanInfo = mgmSanInfos.getJSONObject(i);
			if (mgmSanInfo.getString("id").equals(mgmSanId)) {
				return mgmSanInfo;
			}
		}
		return null;
	}

	/**
	 * 向MGM注册SAN信息
	 * 
	 * @param siteId
	 *            站点编码
	 * @param paramMap
	 *            请求参数
	 * @return JSONObject 操作结果
	 * @throws APIException
	 *             API异常处理类
	 */
	private JSONObject saveSanToMGM(String siteId, Map<String, Object> paramMap) throws APIException {
		String vendor = (String) paramMap.get("vendor");
		SanVendorEntity sanVendor = sanVendorDao.get(vendor);
		JSONObject paramJson = new JSONObject();
		paramJson.put("vendor", sanVendor.getCode());
		paramJson.put("version", sanVendor.getVersion());
		paramJson.put("admin_unit", StringUtils.trim((String) paramMap.get("domain")));
		paramJson.put("lun_start", (Integer) paramMap.get("lunStart"));
		paramJson.put("lun_end", (Integer) paramMap.get("lunEnd"));
		paramJson.put("host_lun_start", (Integer) paramMap.get("hostLunStart"));
		paramJson.put("host_lun_end", (Integer) paramMap.get("hostLunEnd"));

		String urlPattern = "/{0}/storage/san";
		String url = MessageFormat.format(urlPattern, SysConstants.MGM_VERSION);
		RespJson httpRespJson = sendHttpPost(siteId, SysConstants.INTERFACE_TYPE_MGM, url, paramJson.toJSONString());
		if (httpRespJson.getStatus() != HttpStatus.SC_CREATED) {
			throw new APIException(httpRespJson.getMsg());
		}
		return (JSONObject) httpRespJson.getData();
	}

	/**
	 * 删除MGM上的指定SAN信息
	 * 
	 * @param siteId
	 *            站点编码
	 * @param mgmSanId
	 *            MGM SAN编码
	 * @throws APIException
	 *             API异常处理类
	 */
	private void removeSanFromMGM(String siteId, String mgmSanId) throws APIException {
		String urlPattern = "/{0}/storage/san/{1}";
		String url = MessageFormat.format(urlPattern, SysConstants.MGM_VERSION, mgmSanId);
		RespJson httpRespJson = sendHttpDelete(siteId, SysConstants.INTERFACE_TYPE_MGM, url);
		if (httpRespJson.getStatus() != HttpStatus.SC_NO_CONTENT) {
			throw new APIException(httpRespJson.getMsg());
		}
	}

	/**
	 * 构建SAN对象
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return SAN对象
	 */
	private SanEntity buildSan(Map<String, Object> paramMap) {
		SanEntity san = new SanEntity();
		san.setId(PrimaryKeyUtils.uniqueId());
		SiteEntity site = new SiteEntity();
		site.setId((String) paramMap.get("site"));
		san.setSite(site);
		san.setName(StringUtils.trim((String) paramMap.get("name")));
		SanVendorEntity sanVendor = new SanVendorEntity();
		sanVendor.setId(StringUtils.trim((String) paramMap.get("vendor")));
		san.setSanVendor(sanVendor);
		if (paramMap.containsKey("description")) {
			san.setDescription(StringUtils.trim((String) paramMap.get("description")));
		}
		san.setCreateDateTime(systemDao.getCurrentDateTime());
		UserEntity user = getUser();
		String username = user.getUsername();
		san.setCreateUserLoginName(username);
		return san;
	}

	/**
	 * 构建SAN展示对象
	 * 
	 * @param san
	 *            SAN对象
	 * @param showDetail
	 *            是否展示详情
	 * @param mgmSanInfo
	 *            MGM SAN信息
	 * @return SAN展示对象
	 */
	private SanDto buildShowDto(SanEntity san, boolean showDetail, JSONObject mgmSanInfo) {
		SanDto sanDto = new SanDto();
		SiteEntity site = san.getSite();
		sanDto.setSiteId(site.getId());
		sanDto.setSiteName(site.getName());
		sanDto.setId(san.getId());
		sanDto.setName(san.getName());
		SanVendorDto sanVendorDto = new SanVendorDto();
		SanVendorEntity sanVendor = san.getSanVendor();
		sanVendorDto.setId(sanVendor.getId());
		sanVendorDto.setCode(sanVendor.getCode());
		sanVendorDto.setName(sanVendor.getName());
		sanVendorDto.setVersion(sanVendor.getVersion());
		sanDto.setVendor(sanVendorDto);
		if (mgmSanInfo != null) {
			sanDto.setTotal(mgmSanInfo.getLongValue("total"));
			sanDto.setFree(mgmSanInfo.getLongValue("free"));
		}
		sanDto.setDescription(san.getDescription());
		sanDto.setCreateDateTime(DateUtils.dateTimeToString(san.getCreateDateTime()));
		sanDto.setCreateLoginUserName(san.getCreateUserLoginName());
		return sanDto;
	}
}
